//
//  ChatViewController.m
//  kularkDemo
//
//  Created by szblsx2 on 2020/3/18.
//  Copyright © 2020 szblsx. All rights reserved.
//

#import "ChatViewController.h"
#import <Photos/Photos.h>
#import "KLScreenVideoCell1.h"
#import "KLScreenVideoCell2.h"
#import "KLLocalVideoCell.h"
#import "KLRemoteVideoCell.h"

#import "MemberViewController.h"

#import "KLSdk.h"

#import "GCDAsyncSocket.h"
#import "NTESTPCircularBuffer.h"
#import "NTESSocketPacket.h"
#import "NTESI420Frame.h"
#import "NTESYUVConverter.h"

static NSString * const ScreenHoleNotificationName = @"ScreenHoleNotificationName";

void MyHoleNotificationCallback(CFNotificationCenterRef center,
                                void * observer,
                                CFStringRef name,
                                void const * object,
                                CFDictionaryRef userInfo) {
    NSString *identifier = (__bridge NSString *)name;
    NSObject *sender = (__bridge NSObject *)observer;
    NSDictionary *notiUserInfo = @{@"identifier":identifier};
    [[NSNotificationCenter defaultCenter] postNotificationName:ScreenHoleNotificationName
                                                        object:sender
                                                      userInfo:notiUserInfo];
}


static inline BOOL IsIphoneX() {
    BOOL result = NO;
    if (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPhone) {
        return result;
    }
    if (@available(iOS 11.0, *)) {
        UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
        if (mainWindow.safeAreaInsets.bottom > 0.0) {
            result = YES;
        }
    }
    return result;
}

API_AVAILABLE(ios(12.0))

@interface ChatViewController ()
<UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout,
kularkDelegate,
GCDAsyncSocketDelegate>

@property (weak, nonatomic) IBOutlet UILabel *roomNum;

@property (weak, nonatomic) IBOutlet UICollectionView *videoRenderer;
@property (weak, nonatomic) IBOutlet UICollectionViewFlowLayout *flowLayout;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topHeight;

@property (weak, nonatomic) IBOutlet UIButton *muteButton;
@property (weak, nonatomic) IBOutlet UIButton *loudspeakerButton;
@property (weak, nonatomic) IBOutlet UIButton *videoButton;

@property (nonatomic, weak) UIPageControl *pageControl;
//用户信息集合
@property (nonatomic, strong) NSMutableArray <KLMeetUser *> *dataArray;
//需要渲染的焦点下标
@property (nonatomic, assign) NSInteger focusIndex;
//视频流 (上行用户渲染)
@property (nonatomic, strong) AVCaptureSession *localCaptureSession;
//会员列表
@property (nonatomic, strong) MemberViewController *memberVc;

@property (nonatomic, strong) RPSystemBroadcastPickerView *picker;

@property (nonatomic, strong) GCDAsyncSocket *serviceSocket;
@property (nonatomic, strong) NSMutableArray *clientSockets;
@property (nonatomic, assign) NTESTPCircularBuffer *recvBuffer;




@end

@implementation ChatViewController

- (instancetype)init{
    if (self = [super init]) {
        //设置代理
        [KLSdk shared].delegate = self;
    }
    return self;
}

- (void)dealloc
{
    [self removeUploaderEventMonitor];
    [self stopSocket];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    self.navigationController.navigationBar.hidden = YES;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    _topHeight.constant =  IsIphoneX() ? 88 : 64;
    
    self.roomNum.text = self.roomId;
    self.loudspeakerButton.selected = !self.myInfo.openLoudspeaker;
    self.videoButton.selected = !self.myInfo.openVideo;
    self.muteButton.selected = !self.myInfo.openMicrophone;

    
    //    [_videoRenderer registerClass:[KLScreenVideoCell1 class] forCellWithReuseIdentifier:kScreenVideoCell1Identifier];
    //    [_videoRenderer registerClass:[KLScreenVideoCell2 class] forCellWithReuseIdentifier:kScreenVideoCell2Identifier];
    [_videoRenderer registerClass:[KLLocalVideoCell class] forCellWithReuseIdentifier:kLocalVideoCellIdentifier];
    [_videoRenderer registerClass:[KLRemoteVideoCell class] forCellWithReuseIdentifier:kRemoteVideoCellIdentifier];
    [self.view addSubview:_videoRenderer];
    [self.view sendSubviewToBack:_videoRenderer];
    if (@available(iOS 11.0, *)) {
        _videoRenderer.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, KScreenHeight - 170, KScreenWidth, 30)];
    [self.view addSubview:pageControl];
    _pageControl = pageControl;
    
    
}

/**离开房间*/
- (IBAction)clickBtnForChat:(UIButton *)sender
{
    
    UIAlertController *alertController = [UIAlertController
                                          alertControllerWithTitle:@"确定离开会议吗？"
                                          message:nil
                                          preferredStyle: UIAlertControllerStyleActionSheet];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
    UIAlertAction *OKAction = [UIAlertAction actionWithTitle:@"离开会议" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [[KLSdk shared] leaveMeeting];
        [self dismissViewControllerAnimated:YES completion:^{}];
        
    }];
    [alertController addAction:cancelAction];
    [alertController addAction:OKAction];
    [self presentViewController:alertController animated:YES completion:nil];
}

/**开关摄像头*/
- (IBAction)openCamera:(UIButton *)sender
{
    sender.selected = !sender.isSelected;
    [[KLSdk shared] turnOnCamera:!sender.isSelected];
    if (sender.isSelected) {
        [WHToast showMessage:@"关闭摄像头"];
    }else{
        [WHToast showMessage:@"开启摄像头"];
    }
    self.myInfo.openVideo = !sender.isSelected;
    if (self.dataArray.count > 0) {
        [self reloadVideoRender];
    }
}

/**切换摄像头*/
- (IBAction)switchCamera:(UIButton *)sender
{
    sender.selected = !sender.isSelected;
    [[KLSdk shared] switchCamera];
    if (sender.isSelected) {
        [WHToast showMessage:@"切换后置摄像头"];
    }else{
        [WHToast showMessage:@"切换前置摄像头"];
    }
}

/**开关麦克风*/
- (IBAction)openMicrophone:(UIButton *)sender
{
    
    /*静音状态下 暂定允许自己手动开启麦克风 以下逻辑先注释*/
    //    // 临时变量 查看自己是否是主持人
    //    BOOL isManager = NO;
    //    for (KLMeetUser *user in self.dataArray) {
    //        if ([[KLUserInfo shared].userId isEqualToString:user.userId]) {
    //            if (user.isManager) {
    //                isManager = YES;
    //            }
    //            break;
    //        }
    //    }
    //
    //    if (!isManager && self.meetConfig.roomMute) {
    //        [WHToast showMessage:@"已开启全员静音，暂不能发言"];
    //        return;
    //    }
    //
    
    
    sender.selected = !sender.isSelected;
    [[KLSdk shared] turnOnMicrophone:!sender.isSelected];
    if (sender.isSelected) {
        [WHToast showMessage:@"关闭麦克风"];
    }else{
        [WHToast showMessage:@"开启麦克风"];
    }
}

/**开关扬声器*/
- (IBAction)openVoice:(UIButton *)sender
{
    sender.selected = !sender.isSelected;
    [[KLSdk shared] whetherToOpenLoudspeaker:!sender.isSelected];
    if (sender.isSelected) {
        [WHToast showMessage:@"切换听筒播放"];
    }else{
        [WHToast showMessage:@"切换扬声器播放"];
    }
}

/**成员管理*/
- (IBAction)memberList:(UIButton *)sender
{
    if (!_memberVc) {
        _memberVc = [[MemberViewController alloc] init];
    }
    _memberVc.myInfo = self.myInfo;
    _memberVc.dataArray = self.dataArray;
    [_memberVc reload];
    [self.navigationController pushViewController:_memberVc animated:YES];
}

/**更多功能*/
- (IBAction)moreAction:(UIButton *)sender {
    
    //    [WHToast showMessage:@"更多功能"];
    [[KLSdk shared] sendMeetingNotificationWithType:KLNotifiTypeKickoutUser targetUserId:@"32CFB2BB-459C-4B7A-AC16-D16BAEEF98AB" state:YES];
}


/**共享屏幕*/
- (IBAction)shareScreen:(UIButton *)sender
{
    
    if (sender.isSelected) {
        sender.selected = NO;
        
        if ([self.view.subviews containsObject:self.picker]) {
            [self.picker removeFromSuperview];
        }
        [self stopSocket];
        [self removeUploaderEventMonitor];
        return;
    }
    NSLog(@"共享屏幕");
    [self addUploaderEventMonitor];
    
    sender.selected = !sender.isSelected;
    
    if (@available(iOS 12.0, *)) {
        if (![self.view.subviews containsObject:self.picker]) {
            [self.view addSubview:self.picker];
        }
        for (UIView *view in _picker.subviews){
            if ([view isKindOfClass:[UIButton class]]){
                [(UIButton*)view sendActionsForControlEvents:UIControlEventAllEvents];
            }
        }
    }else{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:@"当前系统版本暂不支持屏幕共享功能" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {}]];
        [self presentViewController:alert animated:YES completion:nil];
    }
    
    /**以下录制方式仅支持录制app内录屏 退出 App 无法录制 不满足需求 故不采用以下方法*/
    
    //    else if (@available(iOS 11.0, *)) {
    //        [RPBroadcastActivityViewController loadBroadcastActivityViewControllerWithPreferredExtension:@"com.blsx.kularkDemo.recoderSetupUI" handler:^(RPBroadcastActivityViewController * _Nullable broadcastActivityViewController, NSError * _Nullable error) {
    //            if (error) {
    //                NSLog(@"RPBroadcast err %@", [error localizedDescription]);
    //            }
    //            broadcastActivityViewController.delegate = self;
    //            [self presentViewController:broadcastActivityViewController animated:YES completion:nil];
    //        }];
    //    }else if (@available(iOS 10.0, *)) {
    //        [RPBroadcastActivityViewController loadBroadcastActivityViewControllerWithHandler:^(RPBroadcastActivityViewController * _Nullable broadcastActivityViewController, NSError * _Nullable error) {
    //            if (error) {
    //                NSLog(@"RPBroadcast err %@", [error localizedDescription]);
    //            }
    //            broadcastActivityViewController.delegate = self;
    //            [self presentViewController:broadcastActivityViewController animated:YES completion:nil];
    //        }];
    //    }
    
    //开启local socket
    [self setupSocket];
}


#pragma mark - 屏幕共享Socket

- (void)setupSocket
{
    self.clientSockets = [NSMutableArray array];
    _recvBuffer = (NTESTPCircularBuffer *)malloc(sizeof(NTESTPCircularBuffer)); // 需要释放
    NTESTPCircularBufferInit(_recvBuffer, kRecvBufferMaxSize);
    self.serviceSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    self.serviceSocket.IPv6Enabled = NO;
    NSError *error;
    [self.serviceSocket acceptOnPort:9898 error:&error];
    [self.serviceSocket readDataWithTimeout:-1 tag:0];
    
}

- (void)stopSocket
{
    if (_serviceSocket)
    {
        [_serviceSocket disconnect];
        _serviceSocket = nil;
        [_clientSockets removeAllObjects];
        NTESTPCircularBufferCleanup(_recvBuffer);
    }
}

#pragma mark - GCDAsyncSocketDelegate

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(nullable NSError *)err
{
    NTESTPCircularBufferClear(self.recvBuffer);
    [self.clientSockets removeObject:sock];
}

- (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock
{
    NTESTPCircularBufferClear(self.recvBuffer);
    [self.clientSockets removeObject:sock];
}

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
    NTESTPCircularBufferClear(self.recvBuffer);
    [self.clientSockets addObject:newSocket];
    [newSocket readDataWithTimeout:-1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    static uint64_t currenDataSize = 0;
    static uint64_t targeDataSize = 0;
    
    BOOL isHeader = NO;
    if (data.length == sizeof(NTESPacketHead)) { // 检查是不是帧头
        NTESPacketHead *header = (NTESPacketHead *)data.bytes;
        if (header->version == 1 && header->command_id == 1 && header->service_id == 1) {
            isHeader = YES;
            targeDataSize = header->data_len;
            currenDataSize = 0;
        }
    } else {
        currenDataSize += data.length;
    }
    
    if (isHeader) { // a.接收到新的帧头，需要先把原来的缓存处理或者清空
        [self handleRecvBuffer];
        NTESTPCircularBufferProduceBytes(self.recvBuffer,
                                         data.bytes,
                                         (int32_t)data.length);
    } else if (currenDataSize >= targeDataSize
               && currenDataSize != -1) { // b.加上新来的数据后缓存中已经满足一帧
        NTESTPCircularBufferProduceBytes(self.recvBuffer,
                                         data.bytes,
                                         (int32_t)data.length);
        currenDataSize = -1;
        [self handleRecvBuffer];
    } else { // c.不够一帧，只添加不处理
        NTESTPCircularBufferProduceBytes(self.recvBuffer,
                                         data.bytes,
                                         (int32_t)data.length);
    }
    [sock readDataWithTimeout:-1 tag:0];
}


- (void)handleRecvBuffer
{
    if (!self.clientSockets.count){
        return;
    }
    int32_t availableBytes = 0;
    void * buffer = NTESTPCircularBufferTail(self.recvBuffer, &availableBytes);
    int32_t headSize = sizeof(NTESPacketHead);
    
    if(availableBytes <= headSize) {
        //        NSLog(@" > 不够文件头");
        NTESTPCircularBufferClear(self.recvBuffer);
        return;
    }
    
    NTESPacketHead head;
    memset(&head, 0, sizeof(head));
    memcpy(&head, buffer, headSize);
    uint64_t dataLen = head.data_len;
    
    if(dataLen > availableBytes - headSize && dataLen >0) {
        //        NSLog(@" > 不够数据体");
        NTESTPCircularBufferClear(self.recvBuffer);
        return;
    }
    
    void *data = malloc(dataLen);
    memset(data, 0, dataLen);
    memcpy(data, buffer + headSize, dataLen);
    NTESTPCircularBufferClear(self.recvBuffer); // 处理完一帧数据就清空缓存
    
    if([self respondsToSelector:@selector(onRecvData:)]) {
        @autoreleasepool {
            [self onRecvData:[NSData dataWithBytes:data length:dataLen]];
        };
    }
    free(data);
}

#pragma mark - 数据回调

- (void)onRecvData:(NSData *)data
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NTESI420Frame *frame = [NTESI420Frame initWithData:data];
        CMSampleBufferRef sampleBuffer = [frame convertToSampleBuffer];
        if (sampleBuffer == NULL) {
            return;
        }
        [[KLSdk shared] sendVideoSampleBuffer:sampleBuffer];
        CFRelease(sampleBuffer);
    });
    
}


#pragma mark - kularkDelegate
/**由于用户和视频流不是串行回调 因此需要在用户回调和视频流回调里 先查询对方*/
/** 获取到房间用户列表回调  */
- (void)respRoomUserList:(NSArray<KLMeetUser *> *)userList
{
    [self.dataArray removeAllObjects];
    
    if (_localCaptureSession && userList.count > 0) {
        KLMeetUser *myInfo = userList[0];
        if ([myInfo.userKind isEqualToString:kMeetUserLocal]) {
            myInfo.localCaptureSession = _localCaptureSession;
        }
    }
    [self.dataArray addObjectsFromArray:userList];
    
    [self findUserListAtFocusIndex:self.focusIndex];
    [self reloadVideoRender];
}

/** 新用户进入房间回调  */
- (void)respUserJoinRoom:(KLMeetUser *)newUser
{
    NSLog(@"用户加入了房间");
    [self.dataArray addObject:newUser];
    [self findUserListAtFocusIndex:self.focusIndex];
    [self reloadVideoRender];
    if (_memberVc) {
        [_memberVc reload];
    }
}

/** 房间用户离开回调  */
- (void)respUserLeaveWithUserId:(NSString *)userId
{
    NSLog(@"用户离开了房间");
    [self.dataArray enumerateObjectsUsingBlock:^(KLMeetUser * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj.userId isEqualToString:userId]) {
            [self.dataArray removeObject:obj];
            *stop = YES;
        }
    }];
    [self findUserListAtFocusIndex:self.focusIndex];
    [self reloadVideoRender];
    if (_memberVc) {
        [_memberVc reload];
    }
}

/** 本地添加视频流回调 */
- (void)addLocalCapturerSession:(AVCaptureSession *)captureSession
{
    if (self.dataArray.count > 0 ) {
        KLMeetUser *myInfo = self.dataArray[0];
        if ([myInfo.userKind isEqualToString:kMeetUserLocal]) {
            myInfo.localCaptureSession = captureSession;
            [self reloadVideoRender];
        }
    }else{
        _localCaptureSession = captureSession;
    }
}

/** 远端添加视频流回调 */
- (void)addRemoteMediaStream:(RTCMediaStream *)mediaStream streamId:(NSString *)streamId userId:(NSString *)userId
{
    if (mediaStream.videoTracks.count > 0) {
        [self.dataArray enumerateObjectsUsingBlock:^(KLMeetUser * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj.userId isEqualToString:userId]) {
                obj.streamIds = @[streamId];
                obj.videoTrack = mediaStream.videoTracks[0];
                *stop = YES;
            }
        }];
        [self reloadVideoRender];
    }
}

/** 远端移除媒体回调 */
- (void)removeRemoteMediaStreamWithStreamId:(NSString *)streamId userId:(NSString *)userId
{
    [self.dataArray enumerateObjectsUsingBlock:^(KLMeetUser * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj.userId isEqualToString:userId]) {
            obj.streamIds = @[];
            obj.videoTrack = nil;
        }
    }];
    [self reloadVideoRender];
}

/** 主持人变更回调 */
- (void)resMeetingNotificationWithType:(KLNotifiType)type targetUserId:(NSString *)targetUserId state:(BOOL)state
{
    NSLog(@"我收到广播了啊 类型是%zd",type);
    // type 0.全员静音 1.单人静音、开关麦克风 2.开关摄像头 3.主持人变更 4.会议踢人
    switch (type) {
        case 0:
        {
            
        }
            break;
        case 1:
        {
            
        }
            break;
        case 2:
        {
            
        }
            break;
        case 3:
        {
            [self adminChangedWithAdminId:targetUserId];
        }
            break;
        case 4:
        {
            [self userBeenKickout:targetUserId];
        }
            break;
    }
    
}

- (void)adminChangedWithAdminId:(NSString *)adminId
{
    if (self.dataArray.count > 0) {
        [self.dataArray enumerateObjectsUsingBlock:^(KLMeetUser * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj.userId isEqualToString:adminId]) {
                obj.isManager = YES;
                if ([[KLUserInfo shared].userId isEqualToString:adminId]) {
                    [WHToast showMessage:@"您已经成为主持人"];
                }else{
                    [WHToast showMessage:[NSString stringWithFormat:@"主持人变更为%@",obj.userName]];
                }
            }else{
                obj.isManager = NO;
            }
            
        }];
        [self reloadVideoRender];
        
        if (_memberVc) {
            [_memberVc reload];
        }
    }
}

/** 用户被移出回调 */
- (void)userBeenKickout:(NSString *)userId
{
    if ([userId isEqualToString:[KLUserInfo shared].userId]) {
        [[KLSdk shared] leaveMeeting];
        [self.dataArray removeAllObjects];
        [self reloadVideoRender];
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"您已经被移出了会议" message:@"" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self dismissViewControllerAnimated:YES completion:^{}];
        }]];
        [self presentViewController:alert animated:YES completion:nil];
    }else{
        [self.dataArray enumerateObjectsUsingBlock:^(KLMeetUser * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj.userId isEqualToString:userId]) {
                [WHToast showMessage:[NSString stringWithFormat:@"%@被移出了会议",obj.userName]];
                [self.dataArray removeObject:obj];
                *stop = YES;
            }
        }];
        [self reloadVideoRender];
        
        if (_memberVc) {
            [_memberVc reload];
        }
    }
}

/** 全员静音回调 */
- (void)respRoomMute:(BOOL)mute
{

    self.muteButton.selected = mute;
    [[KLSdk shared] turnOnMicrophone:!mute];
    if (mute) {
        [WHToast showMessage:@"主持人开启了全员静音"];
    }else{
        [WHToast showMessage:@"主持人关闭了全员静音"];
    }
}


#pragma mark - UICollectionViewDelegate,UICollectionViewDataSource

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    //    NSInteger count = ceil(self.dataArray.count /4.0);
    //
    self.pageControl.numberOfPages =  self.dataArray.count;
    self.pageControl.hidden = self.dataArray.count == 1;
    //
    //    return count;
    return self.dataArray.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        //        KLScreenVideoCell1 *videoCell1 = [collectionView dequeueReusableCellWithReuseIdentifier:kScreenVideoCell1Identifier forIndexPath:indexPath];
        //        videoCell1.openLocalVideo = self.meetConfig.openVideo;
        //        [videoCell1 reloadCellWithRemoteVideoTracks:self.dataArray focus:self.focusIndex == indexPath.row];
        //        return videoCell1;
        KLLocalVideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kLocalVideoCellIdentifier forIndexPath:indexPath];
        cell.openLocalVideo = YES;
        [cell reloadCellWithLocalUser:self.dataArray[indexPath.row] focus:YES];
        return cell;
    }else{
        //        KLScreenVideoCell2 *videoCell2 = [collectionView dequeueReusableCellWithReuseIdentifier:kScreenVideoCell2Identifier forIndexPath:indexPath];
        //        [videoCell2 reloadCellWithRemoteVideoTracks:self.dataArray focus:self.focusIndex == indexPath.row atSuperIndex:indexPath.row];
        //        return videoCell2;
        KLRemoteVideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kRemoteVideoCellIdentifier forIndexPath:indexPath];
        [cell reloadCellWithRemoteUser:self.dataArray[indexPath.row] focus:YES];
        return cell;
    }
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
    return 0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    return 0;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat cWidth = collectionView.frame.size.width;
    CGFloat cHeight = collectionView.frame.size.height;
    return CGSizeMake(cWidth, cHeight);
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (scrollView == self.videoRenderer) {
        CGFloat contentOffSetX = scrollView.contentOffset.x;
        //获取占据屏幕中心的item
        NSIndexPath *middleIndexPath = [self.videoRenderer indexPathForItemAtPoint:CGPointMake(contentOffSetX + KScreenWidth/2, 0)];
        if (self.focusIndex != middleIndexPath.row) {
            self.pageControl.currentPage = middleIndexPath.row;
            self.focusIndex = middleIndexPath.row;
            NSLog(@"焦点下标为第%zd页",self.focusIndex);
            [self findUserListAtFocusIndex:self.focusIndex];
        }
    }
}

/**根据焦点下标获取当前屏幕的用户列表*/
- (void)findUserListAtFocusIndex:(NSInteger)focusIndex
{
    NSInteger num = 1;
    
    NSInteger startIndex = self.focusIndex * num;
    
    NSInteger endIndex = self.dataArray.count - startIndex;
    
    NSArray *resultArray = [NSArray array];
    
    if (endIndex <= 0) {
        return;
    }
    
    if (endIndex >= num) {
        resultArray = [self.dataArray subarrayWithRange:NSMakeRange(startIndex, num)];
    }else{
        resultArray = [self.dataArray subarrayWithRange:NSMakeRange(startIndex, self.dataArray.count - startIndex)];
    }
    
    NSMutableArray *userIds = [NSMutableArray arrayWithCapacity:resultArray.count];
    for (KLMeetUser *user in resultArray) {
        [userIds addObject:user.userId];
    }
    [[KLSdk shared] chooseMediaSoucesWithUserIds:userIds];
}

#pragma mark - 录屏通知相关

- (void)addUploaderEventMonitor
{
    NSLog(@"addUploaderEventMonitor");
    [self registerForNotificationsWithIdentifier:kRecoderBroadcastStarted];
    [self registerForNotificationsWithIdentifier:kRecoderBroadcastPaused];
    [self registerForNotificationsWithIdentifier:kRecoderBroadcastResumed];
    [self registerForNotificationsWithIdentifier:kRecoderBroadcastFinished];
    [self registerForNotificationsWithIdentifier:kRecoderSocketConnectFaild];
    //这里同时注册了分发消息的通知，在宿主App中使用
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(broadcastInfo:) name:ScreenHoleNotificationName object:nil];
}

- (void)broadcastInfo:(NSNotification *)noti
{
    NSDictionary *userInfo = noti.userInfo;
    NSString *identifier = userInfo[@"identifier"];
    
    if ([identifier isEqualToString:kRecoderBroadcastStarted]) {
        NSLog(@"开启录屏");
    }
    if ([identifier isEqualToString:kRecoderBroadcastPaused]) {
        NSLog(@"暂停录屏");
    }
    if ([identifier isEqualToString:kRecoderBroadcastResumed]) {
        NSLog(@"恢复录屏");
    }
    if ([identifier isEqualToString:kRecoderBroadcastFinished]) {
        NSLog(@"完成录屏");
        [self stopSocket];
    }
    if ([identifier isEqualToString:kRecoderSocketConnectFaild]) {
        NSLog(@"连接失败");
    }
    
}

- (void)removeUploaderEventMonitor
{
    NSLog(@"removeUploaderEventMonitor");
    [self unregisterForNotificationsWithIdentifier:kRecoderBroadcastStarted];
    [self unregisterForNotificationsWithIdentifier:kRecoderBroadcastPaused];
    [self unregisterForNotificationsWithIdentifier:kRecoderBroadcastResumed];
    [self unregisterForNotificationsWithIdentifier:kRecoderBroadcastFinished];
    [self unregisterForNotificationsWithIdentifier:kRecoderSocketConnectFaild];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:ScreenHoleNotificationName object:nil];
}



- (void)registerForNotificationsWithIdentifier:(nullable NSString *)identifier
{
    [self unregisterForNotificationsWithIdentifier:identifier];
    CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();
    CFStringRef str = (__bridge CFStringRef)identifier;
    CFNotificationCenterAddObserver(center,
                                    (__bridge const void *)(self),
                                    MyHoleNotificationCallback,
                                    str,
                                    NULL,
                                    CFNotificationSuspensionBehaviorDeliverImmediately);
}

- (void)unregisterForNotificationsWithIdentifier:(nullable NSString *)identifier
{
    CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();
    CFStringRef str = (__bridge CFStringRef)identifier;
    CFNotificationCenterRemoveObserver(center,
                                       (__bridge const void *)(self),
                                       str,
                                       NULL);
}


/**视图刷新*/
- (void)reloadVideoRender{
    __weak __typeof(self) ws = self;
    [UIView animateWithDuration:0 animations:^{
        [ws.videoRenderer reloadData];
    }];
}

#pragma mark - Getter

- (NSMutableArray<KLMeetUser *> *)dataArray
{
    if (!_dataArray) {
        _dataArray = [NSMutableArray array];
    }
    return _dataArray;
}

- (RPSystemBroadcastPickerView *)picker
API_AVAILABLE(ios(12.0))
{
    if (!_picker) {
        _picker = [[RPSystemBroadcastPickerView alloc] init];
        _picker.showsMicrophoneButton = NO;
        //你的app对用upload extension的 bundle id， 必须要填写对
        if (@available(iOS 13.0, *)) {
            _picker.preferredExtension = @"com.blsx.kularkDemo.recoder";
        }
    }
    return _picker;
}

@end
